<?php

// ------------------------------------------------------------------------
// |@Author       : Jarmin <edshop@qq.com>
// |@----------------------------------------------------------------------
// |@Date         : 2025-04-20 09:16:21
// |@----------------------------------------------------------------------
// |@LastEditTime : 2025-04-22 21:08:56
// |@----------------------------------------------------------------------
// |@LastEditors  : Jarmin <jarmin@ladmin.cn>
// |@----------------------------------------------------------------------
// |@Description  : 令牌模型 - 用于管理JWT令牌和用户会话
// |@----------------------------------------------------------------------
// |@FilePath     : Token.php
// |@----------------------------------------------------------------------
// |@Copyright (c) 2025 http://www.ladmin.cn   All rights reserved.
// ------------------------------------------------------------------------

namespace think\admin\model;

use think\admin\Model;

/**
 * 令牌管理模型
 * Class Token
 * @package app\admin\model
 */
class Token extends Model
{
    /**
     * 对应数据表
     * @var string
     */
    protected $table = 'system_token';

    /**
     * 类型获取器（将数据库中的类型字符串转为数组）
     *
     * @param string $value 数据库中的类型值
     * @return array 类型数组 [value, text, color]
     */
    public function getTypeAttr(string $value): array
    {
        $types = [
            'access'  => ['value' => 'access', 'text' => lang('model.token_type_access_text'), 'color' => lang('model.token_type_access_color')],
            'refresh' => ['value' => 'refresh', 'text' => lang('model.token_type_refresh_text'), 'color' => lang('model.token_type_refresh_color')]
        ];

        return $types[$value] ?? $types['access'];
    }

    /**
     * 吊销状态获取器
     *
     * @param int $value 数据库中的状态值
     * @return array 状态数组 [value, text, color]
     */
    public function getIsRevokedAttr(int $value): array
    {
        $status = [
            0 => ['value' => 0,'text' => lang('model.token_status_valid_text'), 'color' => lang('model.token_status_valid_color')],
            1 => ['value' => 1,'text' => lang('model.token_status_revoked_text'), 'color' => lang('model.token_status_revoked_color') ]
        ];

        return $status[$value] ?? $status[0];
    }

    /**
     * 用户关联
     *
     * @return \think\model\relation\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * 活跃令牌查询作用域
     *
     * @param \think\db\Query $query 查询构造器
     * @return \think\db\Query
     */
    public function scopeActive($query)
    {
        return $query->where('is_revoked', 0)
            ->where('expired_at', '>', date('Y-m-d H:i:s'));
    }

    /**
     * 类型查询作用域
     *
     * @param \think\db\Query $query 查询构造器
     * @param string $type 令牌类型
     * @return \think\db\Query
     */
    public function scopeOfType($query, string $type)
    {
        return $query->where('type', $type);
    }

    /**
     * 用户查询作用域
     *
     * @param \think\db\Query $query 查询构造器
     * @param int $userId 用户ID
     * @return \think\db\Query
     */
    public function scopeOfUser($query, int $userId)
    {
        return $query->where('user_id', $userId);
    }

    /**
     * 获取设备信息（格式化用户代理字符串）
     *
     * @param string|null $value 原始设备信息
     * @return array 格式化后的设备信息
     */
    public function getDeviceInfoAttr(?string $value = null): array
    {
        if (empty($value)) {
            return [
                'device' => lang('model.token_device_unknown_device'),
                'browser' => lang('model.token_device_unknown_browser'),
                'os' => lang('model.token_device_unknown_os')
            ];
        }

        // 设备类型检测
        $device = lang('model.token_device_type_desktop');
        if (stripos($value, 'mobile') !== false || stripos($value, 'android') !== false) {
            $device = lang('model.token_device_type_mobile');
        }

        // 浏览器检测
        $browser = lang('model.token_device_unknown_browser');
        if (stripos($value, 'chrome') !== false) {
            $browser = lang('model.token_device_browser_chrome');
        } elseif (stripos($value, 'firefox') !== false) {
            $browser = lang('model.token_device_browser_firefox');
        } elseif (stripos($value, 'safari') !== false) {
            $browser = lang('model.token_device_browser_safari');
        } elseif (stripos($value, 'edge') !== false) {
            $browser = lang('model.token_device_browser_edge');
        }

        // 操作系统检测
        $os = lang('model.token_device_unknown_os');
        if (stripos($value, 'windows') !== false) {
            $os = lang('model.token_device_os_windows');
        } elseif (stripos($value, 'mac') !== false) {
            $os = lang('model.token_device_os_macos');
        } elseif (stripos($value, 'linux') !== false) {
            $os = lang('model.token_device_os_linux');
        } elseif (stripos($value, 'android') !== false) {
            $os = lang('model.token_device_os_android');
        } elseif (stripos($value, 'iphone') !== false || stripos($value, 'ipad') !== false) {
            $os = lang('model.token_device_os_ios');
        }

        return [
            'device' => $device,
            'browser' => $browser,
            'os' => $os,
            'raw' => $value
        ];
    }
}
